package com.ly.common.core.utils;

import cn.hutool.core.io.IoUtil;
import com.ly.common.core.config.MinioConfig;
import io.minio.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

/**
 * minio工具类
 *
 * @author luoyun
 * @Date: 2025/5/11 17:05
 * @Note:
 */
public class MinioUtil {

    private static MinioClient minioClient = SpringUtils.getBean(MinioClient.class);
    private static MinioConfig minioConfig = SpringUtils.getBean(MinioConfig.class);
    private static String bucketName = minioConfig.getBucketName();

    /**
     * 检查bucket是否存在
     */
    public static void checkBucket() {
        try {
            boolean isBucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!isBucketExists) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化 MinIO 客户端失败", e);
        }
    }

    /**
     * 上传文件
     *
     * @param file 文件对象
     * @return 文件在 MinIO 中的路径
     */
    public static String uploadFile(MultipartFile file) {
        checkBucket();
        try {
            String fileName = file.getOriginalFilename();
            InputStream stream = file.getInputStream();
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .contentType(getContentType(fileName))
                            .stream(stream, stream.available(), -1).build()
            );
            stream.close();
            return minioConfig.getEndpoint() + "/" + bucketName + "/" + fileName;
        } catch (Exception e) {
            throw new RuntimeException("文件上传失败", e);
        }
    }

    /**
     * 上传文件（字节数组）
     *
     * @param data     文件字节数组
     * @param fileName 文件名
     * @return 文件在 MinIO 中的路径
     */
    public static String uploadFile(byte[] data, String fileName) {
        checkBucket();
        try {
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .stream(new ByteArrayInputStream(data), data.length, -1)
                            .contentType(getContentType(fileName))
                            .build()
            );
            return minioConfig.getEndpoint() + "/" + bucketName + "/" + fileName;
        } catch (Exception e) {
            throw new RuntimeException("文件上传失败", e);
        }
    }

    /**
     * 下载文件
     *
     * @param fileName MinIO 中的文件名
     * @return 文件字节数组
     */
    public static byte[] downloadFile(String fileName) {
        try {
            InputStream inputStream = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .build()
            );
            // return inputStream.readAllBytes();
            return IoUtil.readBytes(inputStream);
        } catch (Exception e) {
            throw new RuntimeException("文件下载失败", e);
        }
    }

    /**
     * 删除文件
     *
     * @param fileName MinIO 中的文件名
     */
    public static void deleteFile(String fileName) {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .build()
            );
        } catch (Exception e) {
            throw new RuntimeException("文件删除失败", e);
        }
    }

    /**
     * 根据文件扩展名获取 Content-Type
     *
     * @param fileName 文件名
     * @return Content-Type
     */
    private static String getContentType(String fileName) {
        String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        switch (fileExtension) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "gif":
                return "image/gif";
            case "pdf":
                return "application/pdf";
            case "doc":
                return "application/msword";
            case "docx":
                return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
            case "xls":
                return "application/vnd.ms-excel";
            case "xlsx":
                return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            case "ppt":
                return "application/vnd.ms-powerpoint";
            case "pptx":
                return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
            case "mp4":
                return "video/mp4";
            case "avi":
                return "video/x-msvideo";
            case "mp3":
                return "audio/mpeg";
            default:
                return "application/octet-stream";
        }
    }
}